import jwt
from datetime import timedelta, datetime
from fastapi import HTTPException, Security
from fastapi.security import OAuth2PasswordBearer
from passlib.context import CryptContext
from apps import cruds
from apps.schemas.token_schema import TokenPayload
from core.setting import settings

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

reusable_oauth2 = OAuth2PasswordBearer(tokenUrl="/api/v1/login/access-token")


def get_password_hash(password: str):
    """
    密码加密
    :param password:
    :return:
    """
    return pwd_context.hash(password)


def verify_password(plain_password: str, hashed_password: str):
    """
    密码校验
    :param plain_password:
    :param hashed_password:
    :return:
    """

    return pwd_context.verify(plain_password, hashed_password)


async def get_current_user(
        token: str = Security(reusable_oauth2),
):
    """
    获取当前登入的用户
    :param token:
    :return:
    """
    try:
        # 解析token
        payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
        token_data = TokenPayload(**payload)
    except jwt.PyJWTError:
        raise HTTPException(status_code=401,
                            detail={'msg': "无法验证凭据"})
    if settings.SERVER_HOST != token_data.domain:
        print('domain', settings.SERVER_HOST, token_data.domain)
        raise HTTPException(status_code=401,
                            detail={'msg': "无法验证凭据"})
    user = await cruds.user_crud.get(model_id=token_data.user_id)
    if not user:
        raise HTTPException(status_code=406,
                            detail={'msg': "用户不存在"})

    if not token_data.password == user.password:
        raise HTTPException(status_code=401,
                            detail={'msg': "密码错误"})
    return user


def create_access_token(*, data: dict, expires_delta: timedelta = None):
    """
    生成token
    :param data:
    :param expires_delta:
    :return:
    """
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire, "sub": "access"})
    encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm="HS256")
    return encoded_jwt


async def get_is_admin(current_user=Security(get_current_user)):
    """
    判断是否是管理员权限
    :param current_user:111111
    :return:
    """
    if not current_user.is_admin:
        raise HTTPException(
            status_code=401,
            detail={'msg': "用户没有足够的权限"})

    return current_user
